import os
import shutil
import subprocess
import json
import platform
import zipfile
from urllib.parse import urljoin
from urllib import request

import core
import data

"""
app.py
requirements.txt
"""
subprocess._cleanup = lambda: None

def get_executable(environment:str) -> str:
    if platform.system().lower() == 'windows':
        d = ["Scripts","python.exe"]
    else:
        d = ["bin","python"]
    return os.path.realpath(os.path.join(environment,*d))

def is_valid_package(package:str) -> None:
    static = False
    pkg = False
    try:
        with open(os.path.join(package,"requirements.txt")) as f: pass
        with open(os.path.join(package,"app.py")) as f: pass
        with open(os.path.join(package,"app.json")) as f: pass
        pkg = True
    except OSError:
        pass
    try:
        with open(os.path.join(package,"static.json")) as f: pass
        static = True
    except OSError:
        pass
    return pkg or static

def is_valid_environment(environment:str) -> None:
    try:
        with open(os.path.join(environment,"pyvenv.cfg")) as f: pass
    except OSError:
        return False
    return True

def create_environment(environment:str, package:str,python_executable:str, pip_mirror=None) -> None:
    create_env = subprocess.Popen(
        [python_executable, "-m", "venv", environment],
        stdout=subprocess.PIPE,
        stdin=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    create_env.wait()

    arguments = [get_executable(environment), "-m", "pip", "install", "-r", os.path.join(package,"requirements.txt")]
    if pip_mirror:
        arguments[4:4] = ["-i",pip_mirror]
    install_requirements = subprocess.Popen(
        [get_executable(environment), "-m", "pip", "install", "-r", os.path.join(package,"requirements.txt")],
        stdout=subprocess.PIPE,
        stdin=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    install_requirements.wait()

def remove_environment(environment:str) -> None:
    if not is_valid_environment(environment):
        raise FileNotFoundError("can't find pyenv.cfg under the selected folder")
    shutil.rmtree(environment)

def create_package(package_file:str,target:str) -> None:
    zip = zipfile.ZipFile(package_file)
    os.makedirs(target,exist_ok=True)
    for file in zip.namelist():
        zip.extract(file, target)

def remove_package(package:str) -> None:
    if not is_valid_package(package):
        raise FileNotFoundError("invalid package")
    shutil.rmtree(package)

def download_package_from_repository(git_executable:str,git_repository:str, target:str):
    if is_valid_environment(target):
        return True
    git_clone = subprocess.Popen(
        [git_executable, "clone","--depth" ,"1", git_repository, target], 
        stdout=subprocess.PIPE,
        stdin=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    git_clone.wait()
    return is_valid_package(target)

def command_package(environment:str, package:str):
    executable = get_executable(environment)
    return " ".join([executable, os.path.join(package,"app.py")])

def run_package(environment:str, package:str):
    executable = get_executable(environment)
    # print(*[executable, os.path.join(package,"app.py")])
    run_package = subprocess.Popen(
        [executable, os.path.join(package,"app.py")], 
        stdout=subprocess.PIPE,
        stdin=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    return run_package

def get_package_meta(repository:str, static=False):
    file = "static.json" if static else "app.json"
    url = repository.rstrip("/") + "/raw/master/" + file
    req = request.Request(url)
    with request.urlopen(req) as f:
        return json.loads(f.read().decode('utf-8'))
    
def check_if_installed(package:str):
    file = os.path.join(data.get_packages_path(),package)
    return is_valid_package(file)